﻿package bdz.dms.core {
	import bdz.common.events.UploadManagerEvent;
	import bdz.common.managers.UploadManager;
	import bdz.dms.data.DMSCollection;
	import bdz.dms.events.DMSEvent;
	import bdz.dms.vo.ContentVO;
	import bdz.dms.vo.SectionVO;
	import bdz.dms.vo.TemplateVO;
	import bdz.dms.vo.UserVO;
	
	import com.adobe.crypto.SHA1;
	
	import flash.events.*;
	import flash.net.URLVariables;
	/**
	* ...
	* @author Donald Martinez
	*/
	public class DMSGateway extends EventDispatcher {
		private static var instance:DMSGateway;
		private var _sid:String;
		private var _user:UserVO;
		private var _config:DMSConfig;
		private var _cpass:String;
		function DMSGateway(paccess:PrivateAccess):void {
			if(paccess == null){
				throw new Error("NullPointerException...");
			}
		}
		private function initialize(cnf:DMSConfig):void {
			instance._config = cnf;
		}
		private function processRequest(data:XML, evt:String, responder:Function, process:Boolean = false):void {
			var hook:DMSDataHook = new DMSDataHook(evt);
			hook.processResults = process;
			hook.contentType = "application/octet-stream";
			hook.location = _config.baseURL + _config.scriptPage;
			hook.addEventListener(evt, responder);
			hook.addEventListener(evt, channelDataProcess);
			hook.sendCompressed(data.toXMLString().split("'").join("´"));
		}
		private function channelDataProcess(evt:DMSEvent):void{
			dispatchEvent(evt);
		}
		private function onLoginStatus(evt:DMSEvent):void {
			if(new XML(evt.data).hasOwnProperty("dms_error")){
				dispatchEvent(new DMSEvent(DMSEvent.LOGIN_FAILED, null))
				return;
			}
			try{
				_user = new UserVO(new XML(evt.data).dms_user[0]);
				_user.password = _cpass;
				_sid = _user.sessionid;
				dispatchEvent(new DMSEvent(DMSEvent.LOGIN_SUCCESSFUL, _user));
			}catch (e:Error) {
				trace(e.message);
				dispatchEvent(new DMSEvent(DMSEvent.LOGIN_FAILED, null))
			}
			
		}
		public static function getInstance(config:DMSConfig = null):DMSGateway {
			if (instance == null) {
				instance = new DMSGateway(new PrivateAccess());
				instance.initialize(config);
			}
			return instance;
		}
		
		public function login(uname:String, pword:String):void {
			var vo:UserVO = new UserVO();
			vo.userName = uname;
			_cpass = vo.password = SHA1.hash(pword);
			var tosend:XML = vo.toXML();
			tosend.@method = "login";
			processRequest(tosend, "loginProcess", onLoginStatus);
		}
		public function getSectionAndContent(pid:Number, responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "section.and.content.get";
			xm.@parent_id = pid;
			processRequest(xm, DMSEvent.SECTION_CONTENT_LOADED, responder, true);
		}
		public function getSections(responder:Function):void {
			var xm:XML = <dms/>;
			xm.@method = "section.get.all";
			processRequest(xm, DMSEvent.SECTION_LOADED, responder, true);
		}
		public function getSectionContents(responder:Function, id:Number = -1):void{
			var xm:XML = <dms/>;
			xm.@method = "section.content.get";
			xm.@section_id = id;
			processRequest(xm, DMSEvent.CONTENT_LOADED, responder, true);
		}
		public function getTemplates(responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "template.get";
			processRequest(xm, DMSEvent.TEMPLATE_LOADED, responder, true);
		}
		public function getUsers(responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "user.get";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.USER_LOADED, responder, true);
		}
		public function updateUser(uvo:UserVO, responder:Function = null):void{
			var xm:XML = uvo.toXML();
			xm.@method = "user.update";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.USER_MODIFIED, responder, true);
		}
		public function updateSection(svo:SectionVO, responder:Function = null):void{
			var xm:XML = svo.toXML();
			xm.@method = "section.update";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.SECTION_MODIFIED, responder, true);
		}
		public function updateTemplate(tvo:TemplateVO, responder:Function = null):void{
			var xm:XML = tvo.toXML();
			xm.@method = "template.update";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.TEMPLATE_MODIFIED, responder, true);
		}
		public function updateContent(cvo:ContentVO, responder:Function = null):void{
			var xm:XML = cvo.toXML();
			xm.@method = "content.update";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.CONTENT_MODIFIED, responder, true);
		}
		public function insertUser(uvo:UserVO, responder:Function = null):void{
			var xm:XML = uvo.toXML();
			xm.@method = "user.insert";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.USER_ADDED, responder, true);
		}
		public function insertSectionBatch(dmsColl:DMSCollection, responder:Function = null):void{
			var xm:XML = <dms_batch/>;
			xm.dms_contents = "";
			xm.@method = "section.insert.batch";
			xm.@token = _sid;
			var counter:Number = 0;
			for each(var cvo:SectionVO in dmsColl){
				xm.dms_contents[counter] = cvo.toXML();
				counter++;
			}
			processRequest(xm, DMSEvent.SECTION_ADDED, responder, true);
		}
		public function insertSection(svo:SectionVO, responder:Function = null):void{
			var xm:XML = svo.toXML();
			xm.@method = "section.insert";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.SECTION_ADDED, responder, true);
		}
		public function insertContentBatch(dmsColl:DMSCollection, responder:Function = null):void{
			var xm:XML = <dms_batch/>;
			xm.dms_contents = "";
			xm.@method = "content.insert.batch";
			xm.@token = _sid;
			var counter:Number = 0;
			for each(var cvo:ContentVO in dmsColl){
				xm.dms_contents[counter] = cvo.toXML();
				counter++;
			}
			
			processRequest(xm, DMSEvent.CONTENT_ADDED, responder, true);
		}
		public function insertContent(cvo:ContentVO, responder:Function = null):void{
			var xm:XML = cvo.toXML();
			xm.@method = "content.insert";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.CONTENT_ADDED, responder, true);
		}
		public function insertTemplate(tvo:TemplateVO, responder:Function = null):void{
			var xm:XML = tvo.toXML();
			xm.@method = "template.save";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.TEMPLATE_ADDED, responder, true);
		}
		public function deleteContentBatch(delColl:DMSCollection, responder:Function = null):void{
			var xm:XML = <dms_batch/>;
			xm.dms_contents = "";
			xm.@method = "content.delete.batch";
			xm.@token = _sid;
			var counter:Number = 0;
			for each(var cvo:ContentVO in delColl){
				xm.dms_contents[counter] = cvo.toXML();
				counter++;
			}
			processRequest(xm, DMSEvent.CONTENT_REMOVED, responder, true);
		}
		public function deleteContent(id:Number, responder:Function = null):void{
			var xm:XML = <dms/>;
			xm.@method = "content.delete";
			xm.@token = _sid;
			xm.@id = id;
			processRequest(xm, DMSEvent.CONTENT_REMOVED, responder, true);
		}
		public function deleteSectionBatch(dmsColl:DMSCollection, responder:Function = null):void{
			var xm:XML = <dms_batch/>;
			xm.dms_contents = "";
			xm.@method = "section.delete.batch";
			xm.@token = _sid;
			var counter:Number = 0;
			for each(var cvo:SectionVO in dmsColl){
				xm.dms_contents[counter] = cvo.toXML();
				counter++;
			}
			processRequest(xm, DMSEvent.SECTION_REMOVED, responder, true);
		}
		public function deleteSection(id:Number, recurse:Boolean =  true, responder:Function = null):void{
			var xm:XML = <dms/>;
			xm.@method = "section.delete";
			xm.@token = _sid;
			xm.@id = id;
			xm.@recurse = Number(recurse);
			processRequest(xm, DMSEvent.SECTION_REMOVED, responder, true);
		}
		public function deleteUser(id:Number, responder:Function = null):void{
			var xm:XML = <dms/>;
			xm.@method = "user.delete";
			xm.@token = _sid;
			xm.@id = id;
			processRequest(xm, DMSEvent.USER_REMOVED, responder, true);
		}
		public function deleteTemplate(id:Number, responder:Function = null):void{
			var xm:XML = <dms/>;
			xm.@method = "template.delete";
			xm.@token = _sid;
			xm.@id = id;
			processRequest(xm, DMSEvent.TEMPLATE_REMOVED, responder, true);
		}
		public function rearrangeSections(sections:Array, responder:Function =null):void{
			var xm:XML = <dms/>;
			xm.@method = "section.rearrange";
			xm.@token = _sid;
			xm.sections = "";
			var counter:Number = 0;
			for each(var sct:SectionVO in sections){
				var xnode = <section/>;
				xnode.section_id = sct.section_id;
				xnode.order = sct.order;
				xm.sections.section[counter] = xnode;
				counter++;
			}
			processRequest(xm, DMSEvent.SECTION_REARRANGED, responder, false);
		}
		public function rearrangeContents(contents:Array, responder:Function = null):void{
			var xm:XML = <dms/>;
			xm.@method = "content.rearrange";
			xm.@token = _sid;
			xm.contents = "";
			var counter:Number = 0;
			for each(var cnt:ContentVO in contents){
				var xnode = <content/>;
				xnode.content_id = cnt.content_id;
				xnode.order = cnt.order;
				xm.contents.content[counter] = xnode;
				counter++;
			}
			processRequest(xm, DMSEvent.CONTENT_REARRANGED, responder, false);
		}
		private function startFileUpload(evt:Event):void{
			var uploader:UploadManager = evt.target as UploadManager;
			var ext:String = uploader.name.split(".")[1].toLowerCase();
			if(ext == "jpg" || ext == "jpeg" || ext == "png"){
				uploader.variables.method = "image.upload";
			}else{
				uploader.variables.method = "file.upload";
			}
			uploader.variables.folder = _config.uploadFolder;
			uploader.variables.token = _sid;
			uploader.uploadFile();
		}
		private function onUploadStart(evt:UploadManagerEvent):void{
			dispatchEvent(evt);
		}
		public function browseForFile(props:Object = null, progressResponder:Function = null, completeResponder:Function = null, errorResponder:Function = null, type:String = null):void{
			var umanager:UploadManager = new UploadManager();
			umanager.addEventListener(UploadManagerEvent.UPLOAD_START, onUploadStart);
			umanager.addEventListener(UploadManagerEvent.UPLOAD_PROGRESS, progressResponder);
			umanager.addEventListener(UploadManagerEvent.UPLOAD_COMPLETE, completeResponder);
			umanager.addEventListener(IOErrorEvent.IO_ERROR, errorResponder);
			umanager.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorResponder);
			switch(type){
				case "images":
					umanager.browseForImage();
				break;
				case "flv":
					umanager.browseForFLV();
				break;
				case "documents":
					umanager.browseForDocuments();
				break;
				default:
					umanager.browseAllTypes();
			}
			umanager.variables = new URLVariables();
			if(props){
				for(var prop:String in props){
					umanager.variables[prop] = props[prop];
				}
			}
			umanager.url = _config.baseURL+_config.scriptPage;
			umanager.addEventListener(Event.SELECT, startFileUpload);
		}
		public function sendGenericMail(addr:String, subject:String, msg:String, from:String, responder:Function = null){
			var xm:XML = <dms/>;
			xm.@method = "send.generic.mail";
			xm.@email = addr;
			xm.@token = _sid;
			xm.@subj = subject;
			xm.@msg = msg;
			xm.@from = from;
			processRequest(xm, DMSEvent.EMAIL_SENT, responder);
		}
		public function forgotPassword(email:String, responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "forgot.password";
			xm.@email = email;
			processRequest(xm, DMSEvent.PASSWORD_RESET, responder, true);
		}
		public function applyTemplate(sid:Number, tid:Number, recurse:Number, responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "template.apply";
			xm.@token = _sid;
			xm.section_id = sid;
			xm.template_id = tid;
			xm.recurse = recurse;
			processRequest(xm, DMSEvent.TEMPLATE_APPLIED, responder, true);
		}
		public function getAppliedTemplates(responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = "template.applied";
			xm.@token = _sid;
			processRequest(xm, DMSEvent.APPLIED_TEMPLATES, responder, true);
		}
		public function getServerVars(method:String, responder:Function):void{
			var xm:XML = <dms/>;
			xm.@method = method;
			xm.@token = _sid;
			processRequest(xm, DMSEvent.SERVER_VARS, responder, false);
		}
		public function get sessionid():String {
			return _sid;
		}
		public function get user():UserVO {
			return _user;
		}
	
		
	}
	
}
/**
 * @private
 * 
 */
class PrivateAccess{}